import request from "@/utils/request";
import { getToken } from "@/utils/auth";

// Get the base API URL from environment or use default
const baseURL = import.meta.env.VITE_APP_BASE_API || "";

export default {
  /**
   * Send a message to the AI and get a streaming response
   * @param {string} prompt - The user's message
   * @param {Array} history - Array of previous messages in {role, content} format
   * @param {string} userId - User ID for caching conversation (optional)
   * @param {Function} onMessage - Callback for each message chunk
   * @param {Function} onComplete - Callback when the response is complete
   * @param {Function} onError - Callback for errors
   */
  streamChat(prompt, history, userId, onMessage, onComplete, onError) {
    // Handle case where userId is actually the onMessage callback (backward compatibility)
    if (typeof userId === 'function') {
      onError = onComplete;
      onComplete = onMessage;
      onMessage = userId;
      userId = null;
    }
    
    // Create fetch request for SSE
    const controller = new AbortController();
    const { signal } = controller;
    
    // Use the URL without /elearning prefix first (mobile version might not need it)
    const apiUrl = `${baseURL}/askAi/chat`;
    // console.log("Sending AI chat request to:", apiUrl);
    // console.log("Request payload:", { prompt, history, userId });
    
    // Add debugging
    const DEBUG = true;
    
    fetch(apiUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': getToken(),
      },
      body: JSON.stringify({ prompt, history, userId }),
      signal
    })
    .then(response => {
      if (!response.ok) {
        throw new Error(`Network response was not ok: ${response.status}`);
      }
      
      if (DEBUG) {
        // console.log('Response headers:', Object.fromEntries([...response.headers]));
        // console.log('Response status:', response.status);
      }
      
      // Check if response is JSON
      const contentType = response.headers.get('content-type');
      if (contentType && contentType.includes('application/json')) {
        if (DEBUG) console.log('Received JSON response');
        // Handle JSON response (non-streaming)
        return response.json().then(data => {
          // console.log('JSON response data:', data);
          if (data.content) {
            onMessage(data.content);
            onComplete(data.content);
          } else {
            throw new Error('Invalid response format');
          }
        });
      }
      
      // Handle streaming response
      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let buffer = '';
      let fullResponse = '';
      let responseCompleted = false; // Add a flag to track completion
      
      // Function to process stream chunks
      function processStream({ done, value }) {
        if (done) {
          if (DEBUG) console.log('Stream complete, final buffer:', buffer);
          
          // Process any remaining data in the buffer
          processBuffer(buffer);
          
          // Complete the stream processing if not already completed
          if (!responseCompleted) {
            if (DEBUG) console.log('Completing response at end of stream');
            responseCompleted = true;
            onComplete(fullResponse);
          }
          return;
        }
        
        // Convert the chunk to text
        const chunk = decoder.decode(value, { stream: true });
        if (DEBUG) console.log('Received chunk:', chunk);
        buffer += chunk;
        
        // Process the buffer and update it
        buffer = processBuffer(buffer);
        
        // Continue reading
        return reader.read().then(processStream);
      }
      
      // Helper function to process buffer content
      function processBuffer(buf) {
        // Special case: if the entire buffer starts with 'data:' and contains JSON
        if (buf.trim().startsWith('data:')) {
          try {
            // Try to extract the JSON part
            const jsonStr = buf.trim().substring(5); // Remove 'data:' prefix
            if (DEBUG) console.log('Found data prefix, extracted:', jsonStr);
            
            const data = JSON.parse(jsonStr);
            if (data.content !== undefined) {
              fullResponse = data.content;
              onMessage(fullResponse);
              
              if (data.isComplete && !responseCompleted) {
                if (DEBUG) console.log('Marking response as complete from data prefix');
                responseCompleted = true;
                onComplete(fullResponse);
              }
            }
            return ''; // Clear buffer after processing
          } catch (e) {
            console.error('Error parsing data: prefix JSON:', e);
            // Continue with normal processing if this fails
          }
        }
        
        // Regular processing with line splitting
        const lines = buf.split('\n');
        let processedUpTo = 0;
        
        for (let i = 0; i < lines.length; i++) {
          const line = lines[i].trim();
          
          // If this isn't the last line, include its length + newline in processedUpTo
          if (i < lines.length - 1) {
            processedUpTo += lines[i].length + 1; // +1 for the newline
          }
          
          if (!line) continue;
          
          if (line.startsWith('data:')) {
            try {
              const jsonStr = line.substring(5).trim();
              if (DEBUG) console.log('Processing SSE data line:', jsonStr);
              
              const data = JSON.parse(jsonStr);
              if (data.content !== undefined) {
                fullResponse = data.content;
                onMessage(fullResponse);
                
                if (data.isComplete && !responseCompleted) {
                  if (DEBUG) console.log('Marking response as complete from SSE data');
                  responseCompleted = true;
                  onComplete(fullResponse);
                }
              }
            } catch (e) {
              console.error('Error parsing SSE JSON:', e);
              
              // Try to extract content directly
              const contentMatch = line.match(/data:\s*{"content":"([^"]+)"/);
              if (contentMatch && contentMatch[1]) {
                fullResponse = contentMatch[1];
                onMessage(fullResponse);
              }
            }
          } else if (line.includes('data:')) {
            // Handle case where 'data:' is in the middle of a line
            const dataParts = line.split('data:');
            if (dataParts.length > 1) {
              try {
                const jsonStr = dataParts[1].trim();
                if (DEBUG) console.log('Processing embedded data:', jsonStr);
                
                const data = JSON.parse(jsonStr);
                if (data.content !== undefined) {
                  fullResponse = data.content;
                  onMessage(fullResponse);
                  
                  if (data.isComplete && !responseCompleted) {
                    if (DEBUG) console.log('Marking response as complete from embedded data');
                    responseCompleted = true;
                    onComplete(fullResponse);
                  }
                }
              } catch (e) {
                console.error('Error parsing embedded JSON:', e);
              }
            }
          }
        }
        
        // Keep any unprocessed content in the buffer
        return buf.substring(processedUpTo);
      }
      
      // Start processing the stream
      return reader.read().then(processStream);
    })
    .catch(error => {
      console.error('Streaming error:', error);
      
      // Try fallback URL with /elearning prefix if the error seems to be endpoint-related
      if (error.message.includes('Network response was not ok') && !apiUrl.includes('/elearning')) {
        // console.log('Trying fallback URL with /elearning prefix');
        
        // If the first request fails, try with the /elearning prefix
        const fallbackUrl = `${baseURL}/elearning/askAi/chat`;
        fetch(fallbackUrl, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': getToken(),
          },
          body: JSON.stringify({ prompt, history, userId }),
          signal
        })
        .then(response => {
          if (!response.ok) {
            throw new Error(`Fallback request failed: ${response.status}`);
          }
          
          // Just get the full response as text for simplicity in the fallback
          return response.text();
        })
        .then(text => {
          // Try to parse as JSON
          try {
            const data = JSON.parse(text);
            if (data.content) {
              onMessage(data.content);
              onComplete(data.content);
            } else {
              onMessage(text);
              onComplete(text);
            }
          } catch (e) {
            // Use as plain text
            onMessage(text);
            onComplete(text);
          }
        })
        .catch(fallbackError => {
          console.error('Fallback request failed:', fallbackError);
          onError(fallbackError);
        });
      } else {
        // Pass the error to the caller
        if (onError) {
          onError(error);
        }
      }
    });
    
    // Return the abort controller to allow cancellation
    return controller;
  },

  /**
   * Send a message to the AI and get a non-streaming response
   * @param {string} prompt - The user's message
   * @param {Array} history - Array of previous messages in {role, content} format
   * @param {string} userId - User ID for caching conversation (optional)
   * @returns {Promise} Promise resolving to the AI response
   */
  async chatWithAi(prompt, history, userId) {
    try {
      // console.log("Sending regular AI chat request");
      const response = await request({
        url: "/askAi/completions", // Using the non-streaming endpoint with elearning prefix
        method: "post",
        data: {
          prompt,
          history,
          userId
        }
      });
      // console.log("Regular AI chat response:", response);
      return response;
    } catch (error) {
      console.error("AI Chat Error:", error);
      throw error;
    }
  },

  /**
   * Clear the conversation history for a user
   * @param {string} userId - User ID whose conversation to clear
   * @returns {Promise} Promise resolving to success message
   */
  async clearConversation(userId) {
    try {
      const response = await request({
        url: `/askAi/conversation/${userId}`,
        method: "delete"
      });
      // console.log("Conversation cleared for user:", userId);
      return response;
    } catch (error) {
      console.error("Error clearing conversation:", error);
      throw error;
    }
  }
}; 